
package net.swa.file.web.action;

import java.awt.Image;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.UUID;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Required;
import net.swa.file.beans.entity.Attachment;
import net.swa.system.service.ICommonService;
import net.swa.system.util.annotation.Log;
import net.swa.system.web.action.AbstractBaseAction;
import net.swa.util.FileUtil;
import net.swa.util.JsonResult;

/***
 * 上传图片裁剪action
 * @author junyu
 *
 */
public class JcropImgAction extends AbstractBaseAction
{
    private static final long serialVersionUID = -3566256767528230895L;
    
    private Logger log = Logger.getLogger(JcropImgAction.class);

    /** 公用方法接口 */
    private ICommonService commonService;

    /**存放上传文件的目录**/
    private String uploadPath;

    /**存放删除文件目录*/
    private String gabagePath;

    /**文件服务器路径**/
    private String httpPath;

    private File file;

    private String fileFileName;

    /**存放上传文件的目录的字目录，由于文件的分类，客户端传入**/
    private String folder;

    private String imageUrl;

    //图片原始宽
    private Double sw;

    //图片原始高
    private Double sh;

    //截图x点
    private Double x;

    //截图y点
    private Double y;

    //截图时候的宽
    private Double w;

    //截图时候的高
    private Double h;

    private int limitwidth;

    private int limitheight;

    /***
     * 上传原图像并返回图片服务路径和位置
     * @return
     * @throws Exception
     */
    @Log(description = "上传原图像并返回图片服务路径和位置")
    public String uploadImg() throws Exception
    {
        JsonResult<Object> json = new JsonResult<Object>();
        String path = uploadPath; //部署时候可配置
        String imgUrl = httpPath + folder + "/" + "resource/";
        File f = new File(path + File.separator + folder);
        if (!f.exists())
        {
            f.mkdirs();
        }
        File target = new File(path + File.separator + folder + File.separator + "resource");//默认存放元图片路径
        if (!target.exists())
        {
            target.mkdirs();
        }
        String sourceName = fileFileName;
        String ext = FileUtil.getExtension(this.fileFileName);
        this.fileFileName = UUID.randomUUID().toString() + "." + ext;
        File desc = new File(target.getAbsoluteFile() + File.separator + this.fileFileName);
        if (validateFile(ext))
        {
            writeFile(this.file, desc);

            json.setSuccess(true);
            //保存到附件表
            //                            Attachment attachment = new Attachment();
            //                            attachment.setName(sourceName);
            //                            attachment.setUuid(imgUrl + fileFileName);//此处也加路径？？
            //                            attachment.setExt(ext);
            //                            attachment.setPath(desc.getAbsolutePath());
            //                            commonService.commonAdd(attachment);
            json.setAttribute("fileName", imgUrl + this.fileFileName);//此图片服务器上可以直接取？？
            json.setAttribute("fileSourceName", path + folder + "/resource/" + this.fileFileName);//此图片服务器上可以直接取？？
            json.setAttribute("sourceName", sourceName);
        }
        else
        {
            log.debug("上传的源图片文件大小或者格式不符合要求");
            json.setSuccess(false);
            json.setMessage("附件大小不符合要求");
        }
        outJson(json);
        return null;
    }

    /**
     * 裁剪图片返回裁剪后的图片名称
     * @return
     * @throws Exception 
     */
    @Log(description = "裁剪图片返回裁剪后的图片名称")
    public String cutImg() throws Exception
    {
        log.debug("开始剪切图片文件");
        JsonResult<Object> json = new JsonResult<Object>();
        if (!StringUtils.isBlank(imageUrl))
        {
            String ext = FileUtil.getExtension(imageUrl);
            String dir = imageUrl.substring(0, imageUrl.indexOf("resource"));//目标目录
            String fname = imageUrl.substring(imageUrl.indexOf("resource") + 9);//目标目录
            String netPath = imageUrl.replace("resource/", "").replace(uploadPath, httpPath);
            File f = new File(imageUrl.trim());
            FileInputStream is = null;
            ImageInputStream iis = null;
            File mindesc = new File(dir + fname);
            if (!mindesc.exists())
            {
                mindesc.delete();
            }
            try
            {
                // 读取图片文件 
                is = new FileInputStream(f);
                Image img = ImageIO.read(f);
                /* 
                 * 返回包含所有当前已注册 ImageReader 的 Iterator，这些 ImageReader 
                 * 声称能够解码指定格式。 参数：formatName - 包含非正式格式名称 .
                 *（例如 "jpeg" 或 "tiff"）等 。 
                */
                String imgType = getImgType(ext);

                Iterator<ImageReader> it = ImageIO.getImageReadersByFormatName(imgType);
                ImageReader reader = it.next();
                // 获取图片流  
                iis = ImageIO.createImageInputStream(is);
                /*  
                 * <p>iis:读取源.true:只向前搜索 </p>.将它标记为 ‘只向前搜索’。
                 * 此设置意味着包含在输入源中的图像将只按顺序读取，可能允许 reader
                 *  避免缓存包含与以前已经读取的图像关联的数据的那些输入部分。
                */
                reader.setInput(iis, true);
                /*  
                 * <p>描述如何对流进行解码的类<p>.用于指定如何在输入时从 Java Image I/O 
                 * 框架的上下文中的流转换一幅图像或一组图像。用于特定图像格式的插件
                 * 将从其 ImageReader 实现的 getDefaultReadParam 方法中返回 
                 * ImageReadParam 的实例。  
                */
                ImageReadParam param = reader.getDefaultReadParam();
                int rwidth = img.getWidth(null);
                int rheight = img.getHeight(null);

                int newWidth = (int) (rwidth * (w / sw));
                int newHeight = (int) (rheight * (h / sh));
                
                x=x*rwidth/sw;
                y=y*rheight/sh;
                /* 
                 * 图片裁剪区域。Rectangle 指定了坐标空间中的一个区域，通过 Rectangle 对象
                 * 的左上顶点的坐标（x，y）、宽度和高度可以定义这个区域。 
                */
                Rectangle rect = new Rectangle(x.intValue(), y.intValue(), newWidth, newHeight);

                // 提供一个 BufferedImage，将其用作解码像素数据的目标。  
                param.setSourceRegion(rect);

                /* 
                 * 使用所提供的 ImageReadParam 读取通过索引 imageIndex 指定的对象，并将
                 * 它作为一个完整的 BufferedImage 返回。
                  */
                BufferedImage bi = reader.read(0, param);

                // 保存新图片  
                ImageIO.write(bi, imgType, mindesc);

                json.setSuccess(true);
                //保存到附件表
                //                Attachment attachment = new Attachment();
                //                attachment.setName(sourceName);
                //                attachment.setUuid(imgUrl + fileFileName);//此处也加路径？？
                //                attachment.setExt(ext);
                //                attachment.setPath(desc.getAbsolutePath());
                //                commonService.commonAdd(attachment);
                json.setAttribute("fileName", netPath);//此图片服务器上可以直接取？？
            }
            finally
            {
                if (is != null)
                    is.close();
                if (iis != null)
                    iis.close();
            }
        }
        else
        {
            log.debug("要剪切图片文件丢失");
            json.setSuccess(false);
            json.setMessage("图片不存在");
        }
        outJson(json);
        return null;
    }

    private String getImgType(String ext)
    {
        if(!StringUtils.isBlank(ext)){
            if (ext.trim().contains("jpg"))
            {
                log.debug("获取图片格式jpg");
                return "jpg";
            }
            else if (ext.trim().contains("png"))
            {
                log.debug("获取图片格式png");
                return "png";
            }
        }
        log.debug("获取图片格式失败"+ext);
        return ext;
    }

    /**
     * 上传原图片并作截图处理
     * @return
     * @throws Exception
     */
    public String uploadSrcImg() throws Exception
    {
        JsonResult<Object> json = new JsonResult<Object>();
        String path = uploadPath; //部署时候可配置

        String imgUrl = httpPath + folder + "/";
        File f = new File(path + File.separator + folder);
        if (!f.exists())
        {
            f.mkdirs();
        }
        File target = new File(path + File.separator + folder + File.separator + "resource");//默认存放元图片路径
        if (!target.exists())
        {
            target.mkdirs();
        }
        String sourceName = fileFileName;
        String ext = FileUtil.getExtension(this.fileFileName);
        this.fileFileName = UUID.randomUUID().toString() + "." + ext;
        File desc = new File(target.getAbsoluteFile() + File.separator + this.fileFileName);
        File mindesc = new File(f.getAbsoluteFile() + File.separator + this.fileFileName);
        if (validateFile(ext))
        {
            writeFile(this.file, desc);
            FileInputStream is = null;
            ImageInputStream iis = null;

            try
            {
                // 读取图片文件 
                is = new FileInputStream(this.file);
                Image img = ImageIO.read(this.file);
                /* 
                 * 返回包含所有当前已注册 ImageReader 的 Iterator，这些 ImageReader 
                 * 声称能够解码指定格式。 参数：formatName - 包含非正式格式名称 .
                 *（例如 "jpeg" 或 "tiff"）等 。 
                */
                Iterator<ImageReader> it = ImageIO.getImageReadersByFormatName("jpg");
                ImageReader reader = it.next();
                // 获取图片流  
                iis = ImageIO.createImageInputStream(is);
                /*  
                 * <p>iis:读取源.true:只向前搜索 </p>.将它标记为 ‘只向前搜索’。
                 * 此设置意味着包含在输入源中的图像将只按顺序读取，可能允许 reader
                 *  避免缓存包含与以前已经读取的图像关联的数据的那些输入部分。
                */
                reader.setInput(iis, true);
                /*  
                 * <p>描述如何对流进行解码的类<p>.用于指定如何在输入时从 Java Image I/O 
                 * 框架的上下文中的流转换一幅图像或一组图像。用于特定图像格式的插件
                 * 将从其 ImageReader 实现的 getDefaultReadParam 方法中返回 
                 * ImageReadParam 的实例。  
                */
                ImageReadParam param = reader.getDefaultReadParam();

                int newWidth = (int) (img.getWidth(null) * (w / sw));
                int newHeight = (int) (img.getHeight(null) * (h / sh));
                /* 
                 * 图片裁剪区域。Rectangle 指定了坐标空间中的一个区域，通过 Rectangle 对象
                 * 的左上顶点的坐标（x，y）、宽度和高度可以定义这个区域。 
                */
                Rectangle rect = new Rectangle(x.intValue(), y.intValue(), newWidth, newHeight);

                // 提供一个 BufferedImage，将其用作解码像素数据的目标。  
                param.setSourceRegion(rect);

                /* 
                 * 使用所提供的 ImageReadParam 读取通过索引 imageIndex 指定的对象，并将
                 * 它作为一个完整的 BufferedImage 返回。
                  */
                BufferedImage bi = reader.read(0, param);

                // 保存新图片  
                ImageIO.write(bi, "jpg", mindesc);

                json.setSuccess(true);
                //保存到附件表
                //                Attachment attachment = new Attachment();
                //                attachment.setName(sourceName);
                //                attachment.setUuid(imgUrl + fileFileName);//此处也加路径？？
                //                attachment.setExt(ext);
                //                attachment.setPath(desc.getAbsolutePath());
                //                commonService.commonAdd(attachment);
                json.setAttribute("fileName", imgUrl + this.fileFileName);//此图片服务器上可以直接取？？
                json.setAttribute("minfileName", imgUrl + "min/" + this.fileFileName);//此图片服务器上可以直接取？？
                json.setAttribute("sourceName", sourceName);
            }
            finally
            {
                if (is != null)
                    is.close();
                if (iis != null)
                    iis.close();
            }
        }
        else
        {
            json.setSuccess(false);
            json.setMessage("附件大小或格式不符合要求");
        }

        outJson(json);
        return null;
    }

    private boolean validateFile(String ext)
    {
        Image img;
        try
        {
            img = ImageIO.read(this.file);
            if (this.limitheight != 0)
            {
                if (img.getHeight(null) > limitheight)
                {
                    return false;
                }
            }
            if (this.limitwidth != 0)
            {
                if (img.getWidth(null) > limitwidth)
                {
                    return false;
                }
            }
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        return true;
    }

    /**
     * 删除文件
     * @return
     * @throws Exception
     */
    public String removeFile() throws Exception
    {
        //        UploadFile file = commonService.commonFind(UploadFile.class, fileId);
        Attachment file = commonService.findByAttribute(Attachment.class, "uuid", fileFileName);
        if (null != file)
        {
            outSuccess();
        }
        else
        {
            outError("附件不存在");
        }
        return null;
    }

    /**
     * 写文件
     * @param src
     * @param desc
     * @throws Exception
     */
    private void writeFile(File src , File desc) throws Exception
    {
        try
        {
            FileInputStream inputStream = new FileInputStream(src);
            OutputStream outputStream = new FileOutputStream(desc);
            byte[] buf = new byte[1024];
            int length = 0;
            while ((length = inputStream.read(buf)) != -1)
            {
                outputStream.write(buf, 0, length);
            }
            outputStream.flush();
            outputStream.close();
            inputStream.close();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    public File getFile()
    {
        /* 241 */return this.file;
    }

    public void setFile(File file)
    {
        /* 245 */this.file = file;
    }

    public String getFileFileName()
    {
        /* 249 */return this.fileFileName;
    }

    public void setFileFileName(String fileFileName)
    {
        /* 253 */this.fileFileName = fileFileName;
    }

    public static long getSerialVersionUID()
    {
        /* 265 */return 7350336710259585825L;
    }

    public String getFolder()
    {
        /* 269 */return this.folder;
    }

    public void setFolder(String folder)
    {
        /* 273 */this.folder = folder;
    }

    public String listPage() throws Exception
    {
        /* 294 */return null;
    }

    public String getUploadPath()
    {
        return this.uploadPath;
    }

    public void setUploadPath(String uploadPath)
    {
        this.uploadPath = uploadPath;
    }

    public String getGabagePath()
    {
        return gabagePath;
    }

    public void setGabagePath(String gabagePath)
    {
        this.gabagePath = gabagePath;
    }

    public String getHttpPath()
    {
        return httpPath;
    }

    public void setHttpPath(String httpPath)
    {
        this.httpPath = httpPath;
    }

    public Double getSw()
    {
        return sw;
    }

    public void setSw(Double sw)
    {
        this.sw = sw;
    }

    public Double getSh()
    {
        return sh;
    }

    public void setSh(Double sh)
    {
        this.sh = sh;
    }

    public Double getX()
    {
        return x;
    }

    public void setX(Double x)
    {
        this.x = x;
    }

    public Double getY()
    {
        return y;
    }

    public void setY(Double y)
    {
        this.y = y;
    }

    public Double getW()
    {
        return w;
    }

    public void setW(Double w)
    {
        this.w = w;
    }

    public Double getH()
    {
        return h;
    }

    public void setH(Double h)
    {
        this.h = h;
    }

    public ICommonService getCommonService()
    {
        return commonService;
    }

    @Required
    @Resource
    public void setCommonService(ICommonService commonService)
    {
        this.commonService = commonService;
    }

    public String getImageUrl()
    {
        return imageUrl;
    }

    public void setImageUrl(String imageUrl)
    {
        this.imageUrl = imageUrl;
    }

    public Integer getLimitwidth()
    {
        return limitwidth;
    }

    public void setLimitwidth(Integer limitwidth)
    {
        this.limitwidth = limitwidth;
    }

    public Integer getLimitheight()
    {
        return limitheight;
    }

    public void setLimitheight(Integer limitheight)
    {
        this.limitheight = limitheight;
    }

}
